/**
 *
 */
package com.hula.onion.book.server.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.io.FileNotFoundException;
import java.net.URL;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;

/**
 * Description: Jedis Utils<br>
 * Create Date: 2017年4月5日 下午5:03:21
 *
 * @author liangbing
 * @version 1.0
 */
public class JedisUtils {

    private static Logger logger = LoggerFactory.getLogger(JedisUtils.class);

    private JedisPool jedisPool = null;

    private JedisUtils() {
        // 初始化redis连接
        try {
            if (jedisPool == null) {
                JedisPoolConfig poolConfig = new JedisPoolConfig();

                ResourceBundle bundle = ResourceBundle.getBundle("redis");

                poolConfig.setMaxTotal(Integer.parseInt(bundle
                        .getString("redis.pool.maxTotal")));
                poolConfig.setMaxIdle(Integer.parseInt(bundle
                        .getString("redis.pool.maxIdle")));
                poolConfig.setMinIdle(Integer.parseInt(bundle
                        .getString("redis.pool.minIdle")));
                poolConfig.setMaxWaitMillis(Integer.parseInt(bundle
                        .getString("redis.pool.maxWaitMillis")));
                poolConfig.setTestOnBorrow(Boolean.parseBoolean(bundle
                        .getString("redis.pool.testOnBorrow")));
                poolConfig.setTestOnReturn(Boolean.parseBoolean(bundle
                        .getString("redis.pool.testOnReturn")));
                poolConfig.setTestWhileIdle(Boolean.parseBoolean(bundle
                        .getString("redis.pool.testWhileIdle")));

                String pwd = bundle.getString("redis.password");
                if (StringUtils.isEmpty(pwd)) {
                    jedisPool = new JedisPool(poolConfig,
                            bundle.getString("redis.ip"), Integer.parseInt(bundle
                            .getString("redis.port")), 10000);
                } else {
                    jedisPool = new JedisPool(poolConfig,
                            bundle.getString("redis.ip"), Integer.parseInt(bundle
                            .getString("redis.port")), 10000, pwd);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
            throw new RuntimeException("Getting Redis connections error!");
        }
    }

    //获取实例
    public static JedisUtils getInstance() {
        return JedisUtilsHolder.instance;
    }

    // ---------------------Key Operation-----------------------//

    @Deprecated
    public Set<String> keys(String pattern) {
        Jedis jedis = null;
        Set<String> ok = null;
        try {
            jedis = jedisPool.getResource();
            ok = jedis.keys(pattern);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return ok;
    }

    //key是否存在
    public boolean exists(String key) {
        Jedis jedis = null;
        boolean ok = false;
        try {
            jedis = jedisPool.getResource();
            ok = jedis.exists(key);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return ok;
    }

    // ---------------------String Operation-----------------------//

    public String set(String key, String value) {
        Jedis jedis = null;
        String ok = null;
        try {
            jedis = jedisPool.getResource();
            ok = jedis.set(key, value);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return ok;
    }

    /**
     * 只有不存在时设置key，并且过期时间为 millis毫秒
     *
     * @param key
     * @param value
     * @param millis
     * @return
     */
    public String set(String key, String value, long millis) {
        Jedis jedis = null;
        String ok = null;
        try {
            jedis = jedisPool.getResource();
            jedis.set(key, value, "NX", "PX", millis);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return ok;
    }

    public String get(String key) {
        Jedis jedis = null;
        String result = null;
        try {
            jedis = jedisPool.getResource();
            result = jedis.get(key);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return result;
    }

    public Long setNX(String key, String value) {
        Jedis jedis = null;
        Long result = null;
        try {
            jedis = jedisPool.getResource();
            // 使用setnx
            result = jedis.setnx(key, value);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return result;
    }

    public String getSet(String key, String value) {
        Jedis jedis = null;
        String result = null;
        try {
            jedis = jedisPool.getResource();
            // 使用setnx
            result = jedis.getSet(key, value);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return result;
    }

    public Long del(String key) {
        Jedis jedis = null;
        Long result = null;
        try {
            jedis = jedisPool.getResource();
            result = jedis.del(key);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return result;
    }

    //递增
    public Long incr(String key) {
        Jedis jedis = null;
        Long result = null;
        try {
            jedis = jedisPool.getResource();
            result = jedis.incr(key);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return result;
    }

    //递减
    public Long decr(String key) {
        Jedis jedis = null;
        Long result = null;
        try {
            jedis = jedisPool.getResource();
            result = jedis.decr(key);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return result;
    }

    // ---------------------list Operation-----------------------//

    public Long rpush(String key, String value) {
        Jedis jedis = null;
        Long result = null;
        try {
            jedis = jedisPool.getResource();
            result = jedis.rpush(key, value);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return result;
    }

    public String lset(String key, long index, String value) {
        Jedis jedis = null;
        String result = null;
        try {
            jedis = jedisPool.getResource();
            result = jedis.lset(key, index, value);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return result;
    }

    //移除列表头部元素并返回
    public String lpop(String key) {
        Jedis jedis = null;
        String result = null;
        try {
            jedis = jedisPool.getResource();
            result = jedis.lpop(key);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return result;
    }

    //根据索引位置获取列表中元素
    public List<String> lrange(String key, long start, long end) {
        Jedis jedis = null;
        List<String> result = null;
        try {
            jedis = jedisPool.getResource();
            result = jedis.lrange(key, start, end);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return result;
    }

    //获取列表长度
    public Long llen(String key) {
        Jedis jedis = null;
        Long result = null;
        try {
            jedis = jedisPool.getResource();
            result = jedis.llen(key);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return result;
    }

    // ---------------------set Operation-----------------------//
    public Long sadd(String key, String value) {
        Jedis jedis = null;
        Long result = null;
        try {
            jedis = jedisPool.getResource();
            result = jedis.sadd(key, value);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return result;
    }

    //remove
    public Long srem(String key, String value) {
        Jedis jedis = null;
        Long result = null;
        try {
            jedis = jedisPool.getResource();
            result = jedis.srem(key, value);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return result;
    }

    public Set<String> smembers(String key) {
        Jedis jedis = null;
        Set<String> result = null;
        try {
            jedis = jedisPool.getResource();
            result = jedis.smembers(key);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return result;
    }

    public boolean sismember(String key, String value) {
        Jedis jedis = null;
        boolean result = false;
        try {
            jedis = jedisPool.getResource();
            result = jedis.sismember(key, value);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return result;
    }

    // ---------------------Hash Operation-----------------------//

    //incr hash field value
    public Long hincrBy(String key, String field, long value) {
        Jedis jedis = null;
        Long result = null;
        try {
            jedis = jedisPool.getResource();
            result = jedis.hincrBy(key, field, value);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return result;
    }

    //get all fields and value
    public Map<String, String> hgetAll(String key) {
        Jedis jedis = null;
        Map<String, String> result = null;
        try {
            jedis = jedisPool.getResource();
            result = jedis.hgetAll(key);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return result;
    }

    //get all values
    public List<String> hvals(String key) {
        Jedis jedis = null;
        List<String> result = null;
        try {
            jedis = jedisPool.getResource();
            result = jedis.hvals(key);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return result;
    }

    //key field exists
    public boolean hexists(String key, String field) {
        Jedis jedis = null;
        boolean result = false;
        try {
            jedis = jedisPool.getResource();
            result = jedis.hexists(key, field);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return result;
    }

    //get key field
    public String hget(String key, String field) {
        Jedis jedis = null;
        String result = null;
        try {
            jedis = jedisPool.getResource();
            result = jedis.hget(key, field);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return result;
    }

    //set key field
    public Long hset(String key, String field, String value) {
        Jedis jedis = null;
        Long result = null;
        try {
            jedis = jedisPool.getResource();
            result = jedis.hset(key, field, value);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return result;
    }

    //jedisUtils instance holder
    private static class JedisUtilsHolder {
        private static JedisUtils instance = new JedisUtils();
    }

    public static void main(String[] args) {

        try {
            URL url = ResourceUtils.getURL(ResourceUtils.CLASSPATH_URL_PREFIX);
            System.out.println(url.getPath());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

}
